﻿using ActiproSoftware.Windows.Shapes;
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using Aspose.Cells;
using CCTool.Scripts.Manager;
using CCTool.Scripts.ToolManagers.Extensions;
using CCTool.Scripts.ToolManagers.Managers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Polygon = ArcGIS.Core.Geometry.Polygon;

namespace CCTool.Scripts.ZT.QJ
{
    /// <summary>
    /// Interaction logic for CreateJZDB2.xaml
    /// </summary>
    public partial class CreateJZDB2 : ArcGIS.Desktop.Framework.Controls.ProWindow
    {
        // 定义一个进度框
        private ProcessWindow processwindow = null;
        string tool_name = "生成界址点表_点面结合";

        public CreateJZDB2()
        {
            InitializeComponent();

            // 初始化参数选项
            textFolderPath.Text = BaseTool.ReadValueFromReg(tool_name, "textFolder");
        }

        private void combox_zd_DropDown(object sender, EventArgs e)
        {
            UITool.AddFeatureLayersToComboxPlus(combox_zd);
        }

        private async void combox_zd_Closed(object sender, EventArgs e)
        {
            // 如果图层有指定的字段，则添加到combox中
            try
            {
                string zd = combox_zd.ComboxText();
                await UITool.InitLayerFieldToComboxPlus(combox_zdh, zd, "ZDDM", "string");
                await UITool.InitLayerFieldToComboxPlus(combox_qlr, zd, "QLRMC", "string");
                await UITool.InitLayerFieldToComboxPlus(combox_mj, zd, "ZDMJ", "float");
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.Message + ee.StackTrace);
                return;
            }
        }

        private void combox_zdh_DropDown(object sender, EventArgs e)
        {
            UITool.AddTextFieldsToComboxPlus(combox_zd.ComboxText(), combox_zdh);
        }

        private void combox_qlr_DropDown(object sender, EventArgs e)
        {
            UITool.AddTextFieldsToComboxPlus(combox_zd.ComboxText(), combox_qlr);
        }

        private void combox_mj_DropDown(object sender, EventArgs e)
        {
            UITool.AddFloatFieldsToComboxPlus(combox_zd.ComboxText(), combox_mj);
        }

        private void combox_jzd_DropDown(object sender, EventArgs e)
        {
            UITool.AddFeatureLayersToComboxPlus(combox_jzd, "Point");
        }

        private async void combox_jzd_Closed(object sender, EventArgs e)
        {
            // 如果图层有指定的字段，则添加到combox中
            try
            {
                string jzd = combox_jzd.ComboxText();
                await UITool.InitLayerFieldToComboxPlus(combox_dh, jzd, "JZDH", "string");
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.Message + ee.StackTrace);
                return;
            }
        }

        private void combox_dh_DropDown(object sender, EventArgs e)
        {
            UITool.AddTextFieldsToComboxPlus(combox_jzd.ComboxText(), combox_dh);
        }

        private void openFolderButton_Click(object sender, RoutedEventArgs e)
        {
            textFolderPath.Text = UITool.OpenDialogFolder();
        }

        private void btn_help_Click(object sender, RoutedEventArgs e)
        {
            string url = "";
            UITool.Link2Web(url);
        }

        private async void btn_go_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 获取数据
                string zd = combox_zd.ComboxText();
                string jzd = combox_jzd.ComboxText();

                string zdh = combox_zdh.ComboxText();
                string qlr = combox_qlr.ComboxText();
                string mj = combox_mj.ComboxText();
                string dh = combox_dh.ComboxText();

                string textFolder = textFolderPath.Text;

                // 写入本地
                BaseTool.WriteValueToReg(tool_name, "textFolder", textFolder);

                // 判断参数是否选择完全
                if (zd == "" || textFolder == "" || jzd == "" || zdh == "" || qlr == "" || mj == "" || dh == "")
                {
                    MessageBox.Show("有必选参数为空！！！");
                    return;
                }

                // 打开进度框
                ProcessWindow pw = UITool.OpenProcessWindow(processwindow, tool_name);
                pw.AddMessageTitle(tool_name);

                Close();

                await QueuedTask.Run(() =>
                {
                    // 检查数据
                    List<string> errs = CheckData();
                    // 打印错误
                    if (errs.Count > 0)
                    {
                        foreach (var err in errs)
                        {
                            pw.AddMessageMiddle(10, err, Brushes.Red);
                        }
                        return;
                    }

                    // 获取点数据
                    Dictionary<string, string> pointDict = GetPointData(jzd, dh);

                    // 复制地籍调查表Excel
                    string excelPath = @$"{textFolder}\界址标示表_{zd}.xls";
                    DirTool.CopyResourceFile(@"CCTool.Data.Excel.杂七杂八.界址点成果表_纳尼.xls", excelPath);
                    // 获取工作薄、工作表
                    string excelFile = ExcelTool.GetPath(excelPath);
                    int sheetIndex = ExcelTool.GetSheetIndex(excelPath);
                    // 打开工作薄
                    Workbook wb = ExcelTool.OpenWorkbook(excelFile);

                    // 遍历宗地
                    FeatureClass featureClass = zd.TargetFeatureClass();
                    using RowCursor rowCursor = featureClass.Search();
                    while (rowCursor.MoveNext())
                    {
                        using Feature feature = rowCursor.Current as Feature;
                        Polygon polygon = feature.GetShape() as Polygon;

                        // 获取宗地信息
                        string ZDH = feature[zdh]?.ToString() ?? "";
                        string ZDMJ = feature[mj]?.ToString() ?? "";
                        string QLR = feature[qlr]?.ToString() ?? "";

                        // 复制sheet
                        // 旧表
                        Worksheet oldWS = wb.Worksheets["示例"];
                        // 创建新表
                        int newSheetIndex = wb.Worksheets.Add();
                        // 新表
                        Worksheet newWS = wb.Worksheets[newSheetIndex];
                        // 设置新表的名称
                        newWS.Name = ZDH;
                        // 复制
                        newWS.Copy(oldWS);

                        Cells cells = newWS.Cells;

                        // 设置分页信息
                        SetPage(polygon, pointDict, cells, ZDH, QLR, ZDMJ);

                        if (polygon != null)
                        {
                            // 获取面要素的所有折点【按西北角起始，顺时针重排】
                            List<List<MapPoint>> mapPoints = ReshotMapPointFromXYList(polygon, pointDict);
                            // 列表加倍，可以回头找到第一个点
                            foreach (var mps in mapPoints)
                            {
                                mps.RemoveAt(mps.Count - 1);
                                mps.AddRange(mps);
                            }

                            int rowIndex = 8;   // 起始行
                            int pointIndex = 1;  // 起始点序号

                            int ptDigit = 3; //  XY小数位数

                            for (int i = 0; i < mapPoints.Count; i++)
                            {
                                // 输出折点的XY值和距离到Excel表
                                double prevX = double.NaN;
                                double prevY = double.NaN;
                                // 记录第一点
                                string firestDH = "";
                                // 距离
                                double initLength = 0;

                                for (int j = 0; j < mapPoints[i].Count; j++)
                                {
                                    // 找点
                                    double xx = Math.Round(mapPoints[i][j].X, ptDigit);
                                    double yy = Math.Round(mapPoints[i][j].Y, ptDigit);
                                    string key = $"{xx}+{yy}";

                                    // 如果是列表中的点
                                    if (pointDict.ContainsKey(key))
                                    {
                                        // 写入点号
                                        cells[rowIndex, 1].Value = pointDict[key];
                                        // 写入序号
                                        cells[rowIndex, 0].Value = $"{pointIndex}";

                                        // 写入折点的XY值
                                        cells[rowIndex, 2].Value = yy;
                                        cells[rowIndex, 3].Value = xx;
                                        // 设置单元格为数字型，小数位数
                                        Aspose.Cells.Style style = cells[rowIndex, 3].GetStyle();
                                        style.Number = 4;   // 数字型
                                        style.Custom = ptDigit switch
                                        {
                                            1 => "0.0",
                                            2 => "0.00",
                                            3 => "0.000",
                                            4 => "0.0000",
                                            _ => null,
                                        };
                                        // 设置
                                        cells[rowIndex, 2].SetStyle(style);
                                        cells[rowIndex, 3].SetStyle(style);

                                        // 计算当前点与上一个点的距离
                                        if (!double.IsNaN(prevX) && !double.IsNaN(prevY))
                                        {
                                            double distance = Math.Sqrt(Math.Pow(mapPoints[i][j].X - prevX, 2) + Math.Pow(mapPoints[i][j].Y - prevY, 2));
                                            // 合计距离
                                            initLength += distance;

                                            if (firestDH != "")
                                            {
                                                // 写入距离
                                                cells[rowIndex - 1, 4].Value = initLength;
                                                if (j == mapPoints[i].Count - 1)
                                                {
                                                    cells[rowIndex + 1, 4].Value = "";
                                                }
                                            }
                                            // 距离还原为0
                                            initLength = 0;
                                        }

                                        // 设置点距格式
                                        Aspose.Cells.Style style2 = cells[rowIndex, 4].GetStyle();
                                        style2.Number = 4;   // 数字型
                                        style2.Custom = 2 switch
                                        {
                                            1 => "0.0",
                                            2 => "0.00",
                                            3 => "0.000",
                                            4 => "0.0000",
                                            _ => null,
                                        };
                                        // 设置
                                        cells[rowIndex + 1, 4].SetStyle(style2);

                                        // 如果回到了第一点，就跳出循环
                                        if (pointDict[key] == firestDH)
                                        {
                                            break;
                                        }
                                        // 标记第一个点的点号
                                        if (firestDH == "")
                                        {
                                            firestDH = pointDict[key];
                                        }

                                        // 是否跨页
                                        if ((rowIndex - 76) % 80 == 0)
                                        {
                                            rowIndex += 12;
                                        }
                                        else
                                        {
                                            rowIndex += 2;
                                            pointIndex++;
                                        }

                                    }

                                    // 如果不是列表中的点，算一下距离
                                    else
                                    {
                                        // 计算当前点与上一个点的距离
                                        if (!double.IsNaN(prevX) && !double.IsNaN(prevY))
                                        {
                                            double distance = Math.Sqrt(Math.Pow(mapPoints[i][j].X - prevX, 2) + Math.Pow(mapPoints[i][j].Y - prevY, 2));
                                            // 合计距离
                                            initLength += distance;

                                        }

                                    }
                                    // 更新上一个点的坐标
                                    prevX = mapPoints[i][j].X;
                                    prevY = mapPoints[i][j].Y;


                                }
                            }
                        }

                    }

                    // 删除模板sheet
                    wb.Worksheets.RemoveAt("示例");


                    // 保存
                    wb.Save(excelFile);
                    wb.Dispose();

                });
                pw.AddMessageEnd();
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.Message + ee.StackTrace);
                return;
            }
        }


        // 重排界址点，从西北角开始，并理清顺逆时针，并且是根据指定的点集
        public static List<List<MapPoint>> ReshotMapPointFromXYList(Polygon polygon, Dictionary<string, string> pointDict, bool isAddFirst = true)
        {
            List<List<MapPoint>> result = new List<List<MapPoint>>();

            // 获取面要素的所有点（内外环）
            List<List<MapPoint>> mapPoints = polygon.MapPointsFromPolygon();
            // 获取每个环的最西北点
            List<List<double>> NWPoints = polygon.NWPointsFromPolygon();

            // 每个环进行处理
            for (int j = 0; j < mapPoints.Count; j++)
            {
                List<MapPoint> newVertices = new List<MapPoint>();
                List<MapPoint> vertices = mapPoints[j];
                // 获取要素的最西北点坐标
                double XMin = NWPoints[j][0];
                double YMax = NWPoints[j][1];

                // 找出西北点【离西北角（Xmin,Ymax）最近的点】
                int targetIndex = 0;
                double maxDistance = 10000000;
                for (int i = 0; i < vertices.Count; i++)
                {
                    // 计算和西北角的距离
                    double distance = Math.Sqrt(Math.Pow(vertices[i].X - XMin, 2) + Math.Pow(vertices[i].Y - YMax, 2));
                    // 并且还得是指定的点
                    string key = $"{Math.Round(vertices[i].X, 3)}+{Math.Round(vertices[i].Y, 3)}";
                    if (pointDict.ContainsKey(key))
                    {
                        // 如果小于上一个值，则保存新值，直到找出最近的点
                        if (distance < maxDistance)
                        {
                            targetIndex = i;
                            maxDistance = distance;
                        }
                    }
                }

                // 根据最近点重排顺序
                newVertices = vertices.GetRange(targetIndex, vertices.Count - targetIndex);
                vertices.RemoveRange(targetIndex, vertices.Count - targetIndex);
                newVertices.AddRange(vertices);

                // 判断顺逆时针，如果有问题就调整反向
                bool isClockwise = newVertices.IsColckwise();
                if (!isClockwise && j == 0)    // 如果是外环，且逆时针，则调整反向
                {
                    newVertices.ReversePoint();
                }
                if (isClockwise && j > 0)    // 如果是内环，且顺时针，则调整反向
                {
                    newVertices.ReversePoint();
                }

                // 在末尾加起始点
                if (isAddFirst)
                {
                    newVertices.Add(newVertices[0]);
                }

                result.Add(newVertices);
            }
            // 返回值
            return result;
        }


        // 生成分页，并设置分页信息
        public static void SetPage(Polygon polygon, Dictionary<string, string> pointDict, Cells cells, string ZDH, string QLR, string ZDMJ)
        {
            // 获取要素的界址点总数
            int pointsCount = 1;

            // 获取面要素的所有折点【按西北角起始，顺时针重排】
            List<List<MapPoint>> mapPoints = polygon.ReshotMapPoint(false);

            // 计算重叠的点的数量
            foreach (var mps in mapPoints)
            {
                foreach (var mp in mps)
                {
                    var key = Math.Round(mp.X, 3) + "+" + Math.Round(mp.Y, 3);
                    if (pointDict.ContainsKey(key))
                    {
                        pointsCount++;
                    }
                }
            }


            // 计算要生成的页数
            long pageCount = (int)Math.Ceiling((double)(pointsCount - 35) / 34) + 1;

            int rowsInPage = 80;    // 每页的行数

            if (pageCount > 1)  // 多于1页
            {
                // 复制分页
                for (int i = 1; i < pageCount; i++)
                {
                    cells.CopyRows(cells, 0, i * rowsInPage, rowsInPage);
                }
            }
            // 设置单元格
            for (int i = 0; i < pageCount; i++)
            {
                // 填写页码
                cells[i * rowsInPage, 4].Value = $"第 {i + 1} 页";
                cells[i * rowsInPage + 1, 4].Value = $"共 {pageCount} 页";
                // 项目名称、地块面积
                cells[i * rowsInPage + 2, 0].Value = $"宗地号：{ZDH} ";
                cells[i * rowsInPage + 3, 0].Value = $"权利人：{QLR} ";
                cells[i * rowsInPage + 4, 0].Value = $"宗地面积(平方米): {ZDMJ} ";

            }
        }


        // 获取点数据
        private Dictionary<string, string> GetPointData(string jzd, string dh)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            int digit = 3;

            FeatureClass featureClass = jzd.TargetFeatureClass();
            using RowCursor rowCursor = featureClass.Search();
            while (rowCursor.MoveNext())
            {
                using Feature feature = rowCursor.Current as Feature;
                MapPoint point = feature.GetShape() as MapPoint;

                double x = Math.Round(point.X, digit);
                double y = Math.Round(point.Y, digit);
                // 点号
                string jzdh = feature[dh]?.ToString() ?? "";

                dict.Add($"{x}+{y}", jzdh);
            }

            return dict;
        }

        private List<string> CheckData()
        {
            List<string> result = new List<string>();

            // 检查字段值是否符合要求


            return result;
        }
    }
}
